﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Windows.Media.Imaging;
using System.ServiceModel.DomainServices.Client;
using System.ServiceModel.DomainServices.Client.ApplicationServices;
using System.ServiceModel.DomainServices;
using SilverlightHVP.Web;


namespace SilverlightHVP.ViewModel
{
   public class State
   {

      public delegate void CurrentItemChangedHandler( object sender, EventArgs e );
      public event CurrentItemChangedHandler CurrentItemChanged;
      public delegate void PositionChangedHandler( object sender, EventArgs e );
      public event PositionChangedHandler PositionChanged;
      public delegate void CurrentTopicChangedHandler( object sender, EventArgs e );
      public event CurrentTopicChangedHandler CurrentTopicChanged;
      public delegate void StateChangedHandler( object sender, EventArgs e );
      public event StateChangedHandler StateChanged;




      private ObservableCollection<Set> Sets = new ObservableCollection<Set>();
      private Set currentSet;
      private int currentItemHolderOffset = 0;
      private void SetCurrentItemHolderOffset()
      {
         for ( int i = 0; i < currentSet.ItemHolders.Count; i++ )
         {
            if ( currentSet.ItemHolders[ i ].theItem == currentItem )
               currentItemHolderOffset = i;
         }
      }

       

       

      private HVPConfigRIAContext itemsContext;
      private HVPConfigRIAContext topicsContext;
      private HVPConfigRIAContext linksContext;
      
      

      private readonly int CurrentSetID = 1;

      public State( int CurrentSetGuid )
      {
         GetNewSet( CurrentSetID );
      }


      internal void SetNextItem()
      {
         if ( currentSet.ItemHolders.Count > currentItemHolderOffset + 1 )
         {
            CurrentItem = currentSet.ItemHolders[ ++currentItemHolderOffset ].theItem;
         }
      }
 

      private void GetNewSet( int setID )
      {
         if ( setID < 0 )
         {
            System.Windows.MessageBox.Show( "That link is not yet implemented" );
            return;
         }
         currentSet = new Set();
         itemsContext = new HVPConfigRIAContext();
         try
         {
             
           var LoadItems = itemsContext.Load<ItemsView>(itemsContext.GetItemsViewsQuery(setID));
           LoadItems.Completed +=new EventHandler(LoadItemsCompleted);
         }
         catch
         {
            System.Windows.MessageBox.Show( "That link is not yet implemented" );
            return;
         }

      }

      

      private void LoadItemsCompleted( object sender, EventArgs e )
      {
         var dbItems = itemsContext.ItemsViews;
         if ( dbItems.Count == 0 )
         {
            System.Windows.MessageBox.Show( "Unable to retrieve items from the database." );
            return;
         }

         ItemHolder holder = null;
         currentSet.ItemHolders = new ObservableCollection<ItemHolder>();
         foreach ( var dbItem in dbItems )
         {
            holder = new ItemHolder();
            var item = new Item( dbItem.ListablesID );
            item.TextToDisplay = dbItem.TextToDisplay;
            item.ItemUri = new Uri( dbItem.ItemUri.ToString() + "/manifest", UriKind.Absolute );
            item.Image = new BitmapImage( new Uri( dbItem.ImageSource, UriKind.Absolute ) );
            holder.theItem = item;
            currentSet.ItemHolders.Add( holder );
         }
         this.CurrentItem = currentSet.ItemHolders[ currentItemHolderOffset ].theItem;
         OnStateChanged();
      }




      private ItemHolder CurrentItemHolder
      {
         get
         {
            foreach ( var itemHolder in currentSet.ItemHolders )
            {
               if ( itemHolder.theItem == currentItem )
               {
                  return itemHolder;
               }
            }
            return null;
         }
      }


      public ObservableCollection<Item> Items
      {
         get
         {
            var items = new ObservableCollection<Item>();

            if ( currentSet == null || currentSet.Items == null || currentSet.Items.Count == 0 )
            {
               var item = new Item( -1 );
               item.TextToDisplay = "Loading Items...";
               items.Add( item );
            }
            else
            {
               items = currentSet.Items;
            }
            return items;
         }
      }

      private Item currentItem = null;
      public Item CurrentItem
      {
         get { return currentItem; }
         set
         {
            currentItem = value;
            SetCurrentItemHolderOffset();
            GetTopicsAndLinksForItem(currentItem.ID);
            OnCurrentItemChanged();
         }
      }

      private void GetTopicsAndLinksForItem( int itemID )
      {
          topicsContext = new HVPConfigRIAContext();
         try
         {
            var LoadTopics = topicsContext.Load( topicsContext.GetTopicsViewsQuery( itemID ) );
            LoadTopics.Completed += new EventHandler( LoadTopicsCompleted );
         }
         catch ( Exception e )
         {
            System.Windows.MessageBox.Show( "No topics found. [" + e.Message + "]" );
            return;
         }

         linksContext = new HVPConfigRIAContext();
         try
         {
            var LoadLinks = linksContext.Load( linksContext.GetLinksViewsQuery( itemID ) );
            LoadLinks.Completed += new EventHandler( LoadLinksCompleted );
         }
         catch { }
      }


      void LoadTopicsCompleted( object sender, EventArgs e )
      {

         var dbTopics = topicsContext.TopicsViews;
         if ( dbTopics.Count > 0 )
            CurrentItemHolder.theTopics = new ObservableCollection<Topic>();
         foreach ( var dbTopic in dbTopics )
         {
            var topic = new Topic();
            topic.ID = dbTopic.TopicsID;
            if ( !string.IsNullOrWhiteSpace( dbTopic.ImageSource ) )
               topic.Image = new BitmapImage( new Uri( dbTopic.ImageSource, UriKind.Absolute ) );
            else
               topic.Image = null;
            topic.TextToDisplay = dbTopic.TextToDisplay;
            topic.TopicOffset = new TimeSpan( 0, 0, dbTopic.Offset );
            CurrentItemHolder.theTopics.Add( topic );
         }
         OnStateChanged();
      }

      void LoadLinksCompleted( object sender, EventArgs e )
      {
         var dbLinks = linksContext.LinksViews;
         if ( dbLinks.Count > 0 )
            CurrentItemHolder.theLinks = new ObservableCollection<Link>();
         foreach ( var dbLink in dbLinks )
         {
            var link = new Link();
            link.ID = dbLink.LinksID;
            link.IsValid = link.ID >= 0;
            link.IntID = dbLink.LinksID;
            if ( !string.IsNullOrWhiteSpace( dbLink.ImageSource ) )
               link.Image = new BitmapImage( new Uri( dbLink.ImageSource, UriKind.Absolute ) );
            else
               link.Image = null;
            link.TextToDisplay = dbLink.TextToDisplay;
            link.TimeToWatchFor = new TimeSpan( 0, 0, dbLink.Offset );
            link.NewSet = dbLink.NewSetID == null ? -1 : Convert.ToInt32( dbLink.NewSetID );
            CurrentItemHolder.theLinks.Add( link );
         }
         OnStateChanged();
      }



      public ObservableCollection<Topic> Topics
      {

         get
         {
            var topics = new ObservableCollection<Topic>();
            if ( CurrentItemHolder == null || CurrentItemHolder.theTopics == null || CurrentItemHolder.theTopics.Count == 0 )
            {
               var topic = new Topic();
               topic.TextToDisplay = "Loading Topics...";
               topics.Add(topic);
            }
            else
            {
               topics = CurrentItemHolder.theTopics;
            }
            return topics;
         }

      }


      private Topic currentTopic = null;
      public Topic CurrentTopic
      {
         get { return currentTopic; }
         set
         {
            if ( value != null )
            {
               currentTopic = value;
               Position = currentTopic.TopicOffset;
               OnCurrentTopicChanged();

            }
         }
      }



      public ObservableCollection<Link> Links
      {
         get
         {
            var links = new ObservableCollection<Link>();
            if ( CurrentItemHolder == null || CurrentItemHolder.theLinks == null || CurrentItemHolder.theLinks.Count == 0 )
            {
               var link = new Link();
               link.TextToDisplay = "Loading Links...";
               links.Add( link );
            }
            else
            {
               links = CurrentItemHolder.theLinks;
            }
            return links;
         }

      }
      
      public Link CurrentLink
      {
         set
         {
            if ( value != null )
            {
               GetNewSet( value.NewSet );
            }
         }
      }

      private TimeSpan position;
      public TimeSpan Position
      {
         get { return position; }
         set
         {
            if ( value != null )
            {
               position = value;
               OnPositionChanged();
            }
         }
      }

      public void OnPositionChanged()
      {
         if ( PositionChanged != null )
         {
            PositionChanged( this, new EventArgs() );
         }
      }


      public void OnCurrentItemChanged()
      {
         if ( CurrentItemChanged != null )
         {
            CurrentItemChanged( this, new EventArgs() );
         }
      }

      public void OnStateChanged()
      {
         if ( StateChanged != null )
         {
            StateChanged( this, new EventArgs() );
         }
      }

      public void OnCurrentTopicChanged()
      {
         if ( CurrentTopicChanged != null )
         {
            CurrentTopicChanged( this, new EventArgs() );
         }
      }

   }
}






